package org.eirudy.shareimage.service.impl;

import java.awt.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.eirudy.shareimage.api.aliyunai.AliYunAiApi;
import org.eirudy.shareimage.api.aliyunai.model.CreateOutPaintingTaskRequest;
import org.eirudy.shareimage.api.aliyunai.model.CreateOutPaintingTaskResponse;
import org.eirudy.shareimage.constant.UserConstant;
import org.eirudy.shareimage.exception.BusinessException;
import org.eirudy.shareimage.exception.ErrorCode;
import org.eirudy.shareimage.exception.ThrowUtils;
import org.eirudy.shareimage.manager.CosManager;
import org.eirudy.shareimage.manager.upload.FilePictureUpload;
import org.eirudy.shareimage.manager.upload.PictureUploadTemplate;
import org.eirudy.shareimage.manager.upload.UrlPictureUpload;
import org.eirudy.shareimage.model.dto.file.UploadPictureResult;
import org.eirudy.shareimage.model.dto.picture.*;
import org.eirudy.shareimage.model.entity.Picture;
import org.eirudy.shareimage.model.entity.Space;
import org.eirudy.shareimage.model.entity.User;
import org.eirudy.shareimage.model.enums.PictureReviewStatusEnum;
import org.eirudy.shareimage.model.vo.PictureVO;
import org.eirudy.shareimage.model.vo.UserVO;
import org.eirudy.shareimage.service.PictureService;
import org.eirudy.shareimage.mapper.PictureMapper;
import org.eirudy.shareimage.utils.ColorSimilarUtils;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author Eirudy
* @description 针对表【picture(图片)】的数据库操作Service实现
* @createDate 2025-05-13 20:00:33
*/
@Slf4j
@Service
public class PictureServiceImpl extends ServiceImpl<PictureMapper, Picture>
    implements PictureService{

    @Resource
    private FilePictureUpload filePictureUpload;

    @Resource
    private UrlPictureUpload uploadPicture;

    @Resource
    private UserServiceImpl userServiceImpl;

    @Resource
    private CosManager cosManager;
    @Resource
    private SpaceServiceImpl spaceServiceImpl;
    @Resource
    private TransactionTemplate transactionTemplate;


    @Resource
    private AliYunAiApi aliYunAiApi;

    public PictureVO uploadPicture(Object inputSource, PictureUploadRequest pictureUploadRequest, User loginUser) {
        //1. 首先判断file是否为空
        ThrowUtils.throwIf(inputSource == null, ErrorCode.PARAMS_ERROR,"文件不能为空");
        //校验空间是否存在，是否有空间权限
        Long spaceId = pictureUploadRequest.getSpaceId();
        if(spaceId != null){
            Space space = spaceServiceImpl.getById(spaceId);
            ThrowUtils.throwIf(space == null,ErrorCode.NOT_FOUND_ERROR,"空间不存在");

//            //校验空间管理员
//            if(!loginUser.getId().equals(space.getUserId())){
//                throw new BusinessException(ErrorCode.NO_AUTH_ERROR,"没有空间权限");
//            }

            //校验一下额度
            if(space.getTotalSize() >= space.getMaxSize()){
                throw new BusinessException(ErrorCode.OPERATION_ERROR,"空间大小不足");
            }
            if(space.getTotalCount() >= space.getMaxCount()){
                throw new BusinessException(ErrorCode.OPERATION_ERROR,"空间条数不足");
            }

        }




        //2. 判断是更新还是创建,先判断picUpRequest是否为空，如果为空就直接新建一条记录
        Long picId;
        if(pictureUploadRequest != null) {
            picId = pictureUploadRequest.getId();
        } else {
            picId = null;
        }
        Picture oldPicture = null;
        //3. 如果是更新，先判断图片是否存在
        if(picId != null){
            oldPicture = this.getById(picId);
           ThrowUtils.throwIf(oldPicture == null,ErrorCode.NOT_FOUND_ERROR,"图片不存在");
//           if(!oldPicture.getUserId().equals(loginUser.getId()) && !loginUser.getUserRole().equals(UserConstant.ADMIN_ROLE)){
//               throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
//           }

           // 校验空间是否一致
           // 没传spaceId则直接复用原有的
           if(spaceId == null){
               if(oldPicture.getSpaceId() != null){
                   spaceId = oldPicture.getSpaceId();
               }

           }else{
               if(ObjUtil.notEqual(oldPicture.getSpaceId(), spaceId)){
                    throw new BusinessException(ErrorCode.PARAMS_ERROR,"空间不一致");
               }
           }
        }

        // 4. 上传图片，得到信息，按照空间划分目录
        String filePathPrefix = null;
        if(spaceId == null){
           filePathPrefix = String.format("/public/%s",loginUser.getId());
        }
        else{
            filePathPrefix = String.format("/space/%s",spaceId);
        }

        // 根据inputSource 的类型，区分上传方式
        PictureUploadTemplate pictureUpload = filePictureUpload;
        if(inputSource instanceof String){
            pictureUpload = uploadPicture;
        }
        UploadPictureResult uploadPictureResult = pictureUpload.uploadPicture(inputSource, filePathPrefix);

        //新建需要保存在数据库的对象
        Picture picture = new Picture();
        BeanUtil.copyProperties(uploadPictureResult, picture);
        picture.setUserId(loginUser.getId());
        picture.setSpaceId(spaceId);

        if(pictureUploadRequest != null && pictureUploadRequest.getName() != null ){
            picture.setName(pictureUploadRequest.getName());
        }

        // 如果是pic 不是空 ，则为更新业务
        if(picId != null){
            picture.setId(picId);
            picture.setEditTime(new Date());
        }

        // 填充审核相关信息
        this.fillReviewParams(picture,loginUser);


        if(spaceId !=null) {
            // 更新空间额度,开启事务。 这里要
            Long finalSpaceId = spaceId;
            transactionTemplate.execute(status -> {
                //上传数据库
                boolean result = this.saveOrUpdate(picture);
                ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "图片上传失败");

                //更新额度，如果是替换图片，要先把原本的删掉。这里 没有做区分，lambda 表达式的mybatis-plus todo
                boolean update = spaceServiceImpl.lambdaUpdate().eq(Space::getId, finalSpaceId)
                        .setSql("totalSize = totalSize +" + picture.getPicSize())
                        .setSql("totalCount = totalCount + 1").update();


                ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "更新空间额度失败");
                return true;
            });
        }else{
            // 如果是公共空间
            //上传数据库
            boolean result = this.saveOrUpdate(picture);
            ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "图片上传失败");
        }
        return PictureVO.objToVo(picture);
    }


    /**
     *  图片查询,仿造userService 的查询写就行了
     * @param pictureQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<Picture> getQueryWrapper(PictureQueryRequest pictureQueryRequest) {
        if (pictureQueryRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "请求参数为空");
        }

        // 获得所有属性
        Long id = pictureQueryRequest.getId();
        String name = pictureQueryRequest.getName();
        String introduction = pictureQueryRequest.getIntroduction();
        String category = pictureQueryRequest.getCategory();
        List<String> tags = pictureQueryRequest.getTags();
        Long picSize = pictureQueryRequest.getPicSize();
        Integer picWidth = pictureQueryRequest.getPicWidth();
        Integer picHeight = pictureQueryRequest.getPicHeight();
        Double picScale = pictureQueryRequest.getPicScale();
        String picFormat = pictureQueryRequest.getPicFormat();
        String searchText = pictureQueryRequest.getSearchText();
        Long userId = pictureQueryRequest.getUserId();
        String sortField = pictureQueryRequest.getSortField();
        String sortOrder = pictureQueryRequest.getSortOrder();
        Date reviewTime = pictureQueryRequest.getReviewTime();
        Integer reviewStatus = pictureQueryRequest.getReviewStatus();
        String reviewMessage = pictureQueryRequest.getReviewMessage();
        Long reviewerId = pictureQueryRequest.getReviewerId();
        Long spaceId = pictureQueryRequest.getSpaceId();
        Boolean nullSpaceId = pictureQueryRequest.isNullSpaceId();
        Date startEditTime = pictureQueryRequest.getStartEditTime();
        Date endEditTime = pictureQueryRequest.getEndEditTime();

        QueryWrapper<Picture> queryWrapper = new QueryWrapper<>();
        if(StrUtil.isNotBlank(searchText)) {
          queryWrapper.and(qw -> qw.like("name", searchText)
                  .or()
                  .like("introduction", searchText));
        }
        queryWrapper.eq(ObjUtil.isNotEmpty(id),"id", id);
        queryWrapper.eq(ObjUtil.isNotEmpty(userId),"userId", name);
        queryWrapper.eq(ObjUtil.isNotEmpty(reviewerId),"reviewerId", reviewerId);
        queryWrapper.eq(ObjUtil.isNotEmpty(spaceId),"spaceId", spaceId);
        queryWrapper.isNull(nullSpaceId,"spaceId");
        queryWrapper.eq(ObjUtil.isNotEmpty(reviewStatus),"reviewStatus", reviewStatus);
        //模糊匹配
        queryWrapper.like(StrUtil.isNotBlank(name),"name", name);
        queryWrapper.like(StrUtil.isNotBlank(introduction),"introduction", introduction);
        queryWrapper.like(StrUtil.isNotBlank(picFormat),"picFormat", picFormat);
        queryWrapper.like(StrUtil.isNotBlank(reviewMessage),"reviewMessage", reviewMessage);
        queryWrapper.ge(ObjUtil.isNotNull(startEditTime), "editTime", startEditTime);
        queryWrapper.le(ObjUtil.isNotNull(endEditTime), "editTime", endEditTime);


        // 填充图片信息
        queryWrapper.eq(StrUtil.isNotBlank(category),"category", category);
        queryWrapper.eq(ObjUtil.isNotEmpty(picSize),"picSize", picSize);
        queryWrapper.eq(ObjUtil.isNotEmpty(picWidth),"picWidth", picWidth);
        queryWrapper.eq(ObjUtil.isNotEmpty(picHeight),"picHeight", picHeight);
        queryWrapper.eq(ObjUtil.isNotEmpty(picScale),"picScale", picScale);

        if(CollUtil.isNotEmpty(tags)){
            for(String tag : tags){
                queryWrapper.like("tag", "\""+tag+"\"");
            }
        }

        queryWrapper.orderBy(StrUtil.isNotBlank(sortField),sortOrder.equals("ascend"),sortField);


        return queryWrapper;
    }

    /**
     *  获得PictureVO,顺便和用户建立关联
     * @param picture
     * @param request httpServlet,用于获取user
     * @return
     */
    @Override
    public PictureVO getPictureVO(Picture picture, HttpServletRequest request) {
        PictureVO pictureVO = PictureVO.objToVo(picture);

        Long userId = pictureVO.getUserId();
        if(userId != null){
            User user = userServiceImpl.getById(userId);
            UserVO userVO = userServiceImpl.getUserVO(user);
            pictureVO.setUser(userVO);
        }
        return pictureVO;
    }


    /**
     * 分页获取图片封装
     */
    @Override
    public Page<PictureVO> getPictureVOPage(Page<Picture> picturePage, HttpServletRequest request) {
        List<Picture> pictureList = picturePage.getRecords();
        Page<PictureVO> pictureVOPage = new Page<>(picturePage.getCurrent(), picturePage.getSize(), picturePage.getTotal());
        if (CollUtil.isEmpty(pictureList)) {
            return pictureVOPage;
        }
        // 对象列表 => 封装对象列表
        List<PictureVO> pictureVOList = pictureList.stream().map(PictureVO::objToVo).collect(Collectors.toList());
        // 1. 关联查询用户信息
        Set<Long> userIdSet = pictureList.stream().map(Picture::getUserId).collect(Collectors.toSet());
        Map<Long, List<User>> userIdUserListMap = userServiceImpl.listByIds(userIdSet).stream()
                .collect(Collectors.groupingBy(User::getId));
        // 2. 填充信息
        pictureVOList.forEach(pictureVO -> {
            Long userId = pictureVO.getUserId();
            User user = null;
            if (userIdUserListMap.containsKey(userId)) {
                user = userIdUserListMap.get(userId).get(0);
            }
            pictureVO.setUser(userServiceImpl.getUserVO(user));
        });
        pictureVOPage.setRecords(pictureVOList);
        return pictureVOPage;
    }

    /**
     * 用于更新和修改图片时判断
     * @param picture
     */
    @Override
    public void validPicture(Picture picture) {
        ThrowUtils.throwIf(picture==null,ErrorCode.PARAMS_ERROR);
        Long id = picture.getId();
        String url = picture.getUrl();
        String introduction = picture.getIntroduction();

        ThrowUtils.throwIf(ObjUtil.isEmpty(id),ErrorCode.PARAMS_ERROR,"id不能为空");

        if(StrUtil.isNotBlank(url)){
            ThrowUtils.throwIf(url.length() > 1024,ErrorCode.PARAMS_ERROR,"url 过长");
        }

        if(StrUtil.isNotBlank(introduction)){
            ThrowUtils.throwIf(introduction.length() > 800,ErrorCode.PARAMS_ERROR,"简介过长");
        }

    }

    /**
     *  审核图片，并且记录审核人的信息
     * @param picture
     * @param loginuser
     */
    @Override
    public void doPictureReview(PictureReviewRequest
            picture, User loginuser) {
        // 1. 校验图片相关参数，1.图片存在，2.图片审核状态
        ThrowUtils.throwIf(picture==null,ErrorCode.PARAMS_ERROR);
        Integer status = picture.getReviewStatus();
        String reviewMessage = picture.getReviewMessage();
        Long id = picture.getId();
        PictureReviewStatusEnum reviewStatusEnum =  PictureReviewStatusEnum.getPictureReviewStatusEnumByValue(status);
        // 校验图片参数：图片状态存在，发送过来需要修改的信息，只能把待审核状态修改为其他状态，不能再次修改为待审核状态
        if(reviewStatusEnum == null || id == null || PictureReviewStatusEnum.REVIEWING.equals(reviewStatusEnum)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }

        // 判断图片存在
        Picture oldPicture = this.getById(id);
        ThrowUtils.throwIf(oldPicture==null,ErrorCode.NOT_FOUND_ERROR);

        // 判断重复修改
        if(Objects.equals(oldPicture.getReviewStatus(), status)){
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }



        // 数据库操作
        Picture newPicture = new Picture();
        BeanUtil.copyProperties(picture, newPicture);
        newPicture.setUserId(loginuser.getId());
        newPicture.setReviewTime(new Date());
        boolean result = this.updateById(newPicture);
        ThrowUtils.throwIf(!result,ErrorCode.OPERATION_ERROR);
    }

    /**
     *  把审核的参数修改为待审核之类的，修改审核时间，修改审核人id
     * @param picture
     * @param user
     */
    public void  fillReviewParams(Picture picture,User user){
        if(userServiceImpl.isAdmin(user)){
            //管理员自动过审
            picture.setReviewTime(new Date());
            picture.setReviewStatus(PictureReviewStatusEnum.PASS.getValue());
            picture.setReviewerId(user.getId());
            picture.setReviewMessage("自动过审");
        }
        else{
            //非管理员全部改成待审核
            picture.setReviewStatus(PictureReviewStatusEnum.REVIEWING.getValue());
        }
    }

    /**
     * 批量抓取图片
     *
     * @param pictureUploadByBatchRequest
     * @param user
     */
    @Override
    public Integer uploadPictureByBatch(PictureUploadByBatchRequest pictureUploadByBatchRequest, User user) {
        String searchText = pictureUploadByBatchRequest.getSearchText();
        Integer count = pictureUploadByBatchRequest.getCount();
        String namePrefix = pictureUploadByBatchRequest.getNamePrefix();
        ThrowUtils.throwIf(count > 30,ErrorCode.PARAMS_ERROR,"最多30条");

        //如果namePrefix为空，给一个默认值
        if(StrUtil.isBlank(namePrefix)){
            namePrefix = searchText;
        }

        //抓取内容  todo, 这一块学一下？
        String fetchurl = String.format("https://cn.bing.com/images/async?q=%s&mmasync=1",searchText);
        Document document;
        try {
            document = Jsoup.connect(fetchurl).get();
        } catch (Exception e) {
            log.error("获得失败",e);
            throw new BusinessException(ErrorCode.OPERATION_ERROR,"获取页面失败");
        }

        //获得元素
        Element div = document.getElementsByClass("dgControl").first();
        if(ObjUtil.isEmpty(div)){
            throw new BusinessException(ErrorCode.OPERATION_ERROR,"获取元素失败");
        }

       Elements imgList =  div.select("img.mimg");
        int uploadCount = 0;
        for(Element img : imgList){
            String fileUrl = img.attr("src");
            if(StrUtil.isBlank(fileUrl)){
                log.info("当前链接为空，跳过：{}",fileUrl);
                continue;
            }

            // 处理地址，防止转义
            int questionMarkIndex = fileUrl.indexOf("?");
            if(questionMarkIndex > -1){
                fileUrl = fileUrl.substring(0, questionMarkIndex);
            }
            PictureUploadRequest pictureUploadRequest = new PictureUploadRequest();
            pictureUploadRequest.setUrl(fileUrl);
            pictureUploadRequest.setName(namePrefix+(uploadCount+1));
            try {
                PictureVO pictureVO = this.uploadPicture(fileUrl,pictureUploadRequest,user);
                log.info("图片上传成功,id= {} ",pictureVO.getId());
                uploadCount++;
            } catch (Exception e) {
                log.info("图片上传失败",e);
                continue;

            }

            if (uploadCount >= count) break;

        }
        return uploadCount;
    }

    /**
     * 清除图片，单开一个线程处理，负责将图片对象从对象存储cos中删除
     *
     * @param oldpicture
     */
    @Async
    @Override
    public void clearPicture(Picture oldpicture) {
        try{
        URL fileUrl = new URL(oldpicture.getUrl());
        String url =fileUrl.getFile();
        cosManager.deleteObject(url);
        }
        catch (Exception e) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"数据错误，请联系管理员");
        }
    }

    @Override
    public void checkPictureAuth(User loginuser, Picture picture) {
        Long spaceId = picture.getSpaceId();
        Long loginUserId = loginuser.getId();
        if(spaceId == null){
            //公共图库，仅管理员和本人可以校验
            if(!Objects.equals(loginUserId, picture.getUserId())
                    && !userServiceImpl.isAdmin(loginuser)){
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR,"没有权限");
            }
        }else{
            //私有空间，仅空间管理员可以操作
            if(!picture.getUserId().equals(loginUserId)){
                throw new BusinessException(ErrorCode.NO_AUTH_ERROR,"仅空间管理员可以操作");
            }
        }
    }

    @Override
    public void deletePicture(Long pictureId, User loginUser) {
        long id = pictureId;
        Picture oldPicture = this.getById(id);

        if(oldPicture == null){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }

        // 校验一下权限
        //this.checkPictureAuth(loginUser,oldPicture) ;


        transactionTemplate.execute(status -> {

            if(oldPicture.getSpaceId() != null) {
                //如果是个人空间的picture更新额度，如果是替换图片，要先把原本的删掉。lambda 表达式的mybatis-plus todo理论上来说这里应该先把原本的加上
                boolean update = spaceServiceImpl.lambdaUpdate().eq(Space::getId, oldPicture.getSpaceId())
                        .setSql("totalSize = totalSize +" + oldPicture.getPicSize())
                        .setSql("totalCount = totalCount + 1")
                        .update();

                ThrowUtils.throwIf(!update, ErrorCode.OPERATION_ERROR, "更新空间额度失败");
            }
            //先更新额度，再从数据库删除，避免bug
            boolean result = this.removeById(id);
            ThrowUtils.throwIf(!result,ErrorCode.OPERATION_ERROR);
            return true;
        });


        // 删除图片之后要从数据库把图片清除
        this.clearPicture(oldPicture);
    }

    @Override
    public void editPicture(PictureEditRequest pictureEditRequest, User loginUser) {
        Picture oldPicture = this.getById(pictureEditRequest.getId());

        if(oldPicture == null){
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }

        //校验编辑人权限
        //this.checkPictureAuth(loginUser,oldPicture);

        Picture picture = new Picture();
        BeanUtil.copyProperties(pictureEditRequest, picture);
        picture.setTags(JSONUtil.toJsonStr(pictureEditRequest.getTags()));

        picture.setEditTime(new Date());

        this.validPicture(picture);

        //补充审核参数
        this.fillReviewParams(picture,loginUser);

        boolean result = this.updateById(picture);
        ThrowUtils.throwIf(!result,ErrorCode.OPERATION_ERROR);
    }

    @Override
    public List<PictureVO> searchPictureByColor(Long spaceId, String picColor, User loginUser) {
        //1.校验参数
        ThrowUtils.throwIf(spaceId == null || StrUtil.isBlank(picColor), ErrorCode.PARAMS_ERROR);
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NO_AUTH_ERROR);
        //2.校验空间权限
        Space space = spaceServiceImpl.getById(spaceId);
        ThrowUtils.throwIf(space == null, ErrorCode.NOT_FOUND_ERROR, "空间不存在");
        if (!space.getUserId().equals(loginUser.getId())) {
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }
        //3.查询该空间下的所有图片（必须有主色调）
        List<Picture> pictureList = this.lambdaQuery()
                .eq(Picture::getSpaceId, spaceId)
                .isNotNull(Picture::getPicColor)
                .list();
        //把颜色转化为主色调
        Color targetColor = Color.decode(picColor);

        //计算相似度并排序
        List<Picture> sortedPictureList = pictureList.stream()
                .sorted(Comparator.comparingDouble(picture -> {
                    String hexColor = picture.getPicColor();
                    Color color = Color.decode(hexColor);
                    if (StrUtil.isBlank(hexColor)) {
                        return Double.MAX_VALUE;
                    }

                    return -ColorSimilarUtils.calculateSimilarity(targetColor, color);

                }))
                .limit(12)
                .collect(Collectors.toList());

        // 5.返回结果
        return sortedPictureList.stream().map(PictureVO::objToVo).collect(Collectors.toList());
    }


    /**
     * 批量更新标签
     * @param pictureEditByBatchRequest
     * @param loginUser
     */
    @Override
    public void editPictureByBatch(PictureEditByBatchRequest pictureEditByBatchRequest, User loginUser) {
        // 1. 校验参数
        List<Long> pictureIdList = pictureEditByBatchRequest.getPictureIdList();
        Long spaceId = pictureEditByBatchRequest.getSpaceId();
        String category = pictureEditByBatchRequest.getCategory();
        List<String> tags = pictureEditByBatchRequest.getTags();
        ThrowUtils.throwIf(CollUtil.isEmpty(pictureIdList), ErrorCode.PARAMS_ERROR);
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NO_AUTH_ERROR);
        ThrowUtils.throwIf(spaceId == null, ErrorCode.PARAMS_ERROR);

        // 2. 校验空间权限（获得空间的所有人id,比较LoginUser）
        Space space = spaceServiceImpl.getById(spaceId);
        if(!loginUser.getId().equals(space.getUserId())){
            throw new BusinessException(ErrorCode.NO_AUTH_ERROR);
        }

        // 3. 查询指定图片是否存在，仅选择需要的字段 pictureId,SpaceId ?为什么是需要这两个字段?根据二级索引？
        List<Picture> pictureList = this.lambdaQuery()
                .select(Picture::getId,Picture::getSpaceId)
                .eq(Picture::getSpaceId,space.getId())
                .in(Picture::getId,pictureIdList)
                .list();
        if(pictureList == null) return;
        // 4. 更新分类等等等等
        pictureList.forEach(picture -> {
            if(CollUtil.isNotEmpty(tags)){
                picture.setTags(JSONUtil.toJsonStr(tags));
            }
           if(StrUtil.isNotBlank(category)){
               picture.setCategory(category);
            }
            picture.setEditTime(new Date());

        });

        //批量设置图片姓名
        fillPictureWithNameRule(pictureList,pictureEditByBatchRequest.getNameRule());


        // 5. 操作数据库
        boolean result = this.updateBatchById(pictureList);
        ThrowUtils.throwIf(!result,ErrorCode.OPERATION_ERROR,"更新失败");
    }

    /**
     * nameRule 格式：图片{序号}
     *
     * @param pictureList
     * @param nameRule
     */
    private void fillPictureWithNameRule(List<Picture> pictureList, String nameRule) {
        if (CollUtil.isEmpty(pictureList) || StrUtil.isBlank(nameRule)) {
            return;
        }
        long count = 1;
        try {
            for (Picture picture : pictureList) {
                String pictureName = nameRule.replaceAll("\\{序号}", String.valueOf(count++));
                picture.setName(pictureName);
            }
        } catch (Exception e) {
            log.error("名称解析错误", e);
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "名称解析错误");
        }
    }

    /**
     *  创建扩图任务
     */
    public CreateOutPaintingTaskResponse createPictureOutPaintingTask(CreatePictureOutPaintingTaskRequest createPictureOutPaintingTaskRequest, User loginUser) {
       Long picId = createPictureOutPaintingTaskRequest.getPictureId();

       // 获取图片信息
       Picture picture = Optional.ofNullable(this.getById(picId))
               .orElseThrow(() -> new BusinessException(ErrorCode.NOT_FOUND_ERROR,"图片不存在"));


       // 权限校验
       //checkPictureAuth(loginUser, picture);

       // 创建扩图任务
        CreateOutPaintingTaskRequest createOutPaintingTaskRequest = new CreateOutPaintingTaskRequest();
        CreateOutPaintingTaskRequest.Input input = new CreateOutPaintingTaskRequest.Input();
        input.setImageUrl(picture.getUrl());
        createOutPaintingTaskRequest.setInput(input);
        createOutPaintingTaskRequest.setParameters(createPictureOutPaintingTaskRequest.getParameters());

       // 调用任务

        return aliYunAiApi.createOutPaintingTask(createOutPaintingTaskRequest);

    }
}




